/*
 * Copyright 2011 yura.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.opu.queryhandler.n.client.ui.widgets;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.RoundRectangle2D.Double;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringReader;
import java.sql.SQLWarning;
import java.util.Collection;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.text.EditorKit;
import jsyntaxpane.DefaultSyntaxKit;
import org.opu.queryhandler.n.client.ui.actions.db.DbAction;
import org.opu.queryhandler.n.client.ui.i18n.SqlEditPaneI18N;
import org.opu.queryhandler.n.util.Logger;
import org.opu.queryhandler.n.util.TextResource;

/**
 *
 * @author yura
 */
public class SqlEditPane extends JPanel implements TextResource {

    // init SyntaxKit (editor kit for syle pane)
    static {
        DefaultSyntaxKit.getContentTypes();
    }
    private Logger logger = Logger.getInstance();
    private JScrollPane scrollPane;
    private JEditorPane syntaxPane;
    private SqlEditPaneI18N i18n;
    /** Main tab container */
    private JTabbedPane tabWindow;
    /** cut, copy, paste, ... */
    private JToolBar editToolBar;
    /** run, commit, rollback, autocommit */
    @Deprecated
    private JToolBar sqlToolBar;

    public SqlEditPane(JTabbedPane tabWindow) {
        this(new SqlEditPaneI18N(), tabWindow);
    }

    public SqlEditPane(SqlEditPaneI18N i18n, JTabbedPane tabWindow) {
        super(new BorderLayout());

        this.i18n = i18n;
        this.tabWindow = tabWindow;
        scrollPane = new JScrollPane();
        syntaxPane = new JEditorPane();
        editToolBar = new JToolBarImpl();
        sqlToolBar = new JToolBarImpl();
        sqlToolBar.setOrientation(JToolBar.VERTICAL);

        syntaxPane.setFont(new Font("Monospaced", 0, 14));  //TODO: customize prop
        syntaxPane.setCaretColor(new Color(153, 204, 255)); //TODO: customize prop
        syntaxPane.setBackground(Color.WHITE);
        scrollPane.setViewportView(syntaxPane);
        scrollPane.getViewport().setBackground(Color.WHITE);

        editToolBar.setRollover(true);
        editToolBar.setFocusable(false);

        String lang = "text/sql";

        // install a new DefaultSyntaxKit on the JEditorPane for the requested language.
        syntaxPane.setContentType(lang);

        // Recreate the Toolbar
        editToolBar.removeAll();
        //TODO: add save, saveas, open(checkbox)
        EditorKit kit = syntaxPane.getEditorKit();
        if (kit instanceof DefaultSyntaxKit) {
            DefaultSyntaxKit defaultSyntaxKit = (DefaultSyntaxKit) kit;
            defaultSyntaxKit.addToolBarActions(syntaxPane, editToolBar);
        }

        editToolBar.validate();
        try {
            // setText should not be called (read the JavaDocs).  Better use the read
            // method and create a new document.
            syntaxPane.read(new StringReader(""), lang);
        } catch (IOException ex) {
            logger.info(SqlEditPane.class, "Can't reload text");
            logger.debug(SqlEditPane.class, ex);
        }
        syntaxPane.requestFocusInWindow();

        init();
    }

    public void reinit() {
        init();
    }

    private void init() {
        add(scrollPane);
        add(editToolBar, BorderLayout.NORTH);
//        add(sqlToolBar, BorderLayout.WEST);
    }

    public void setDbActions(Collection<DbAction> actions) {
        sqlToolBar.removeAll();
        for (DbAction action : actions) {
            sqlToolBar.add(action);
        }
    }

    @Override
    public String getText() {
        return syntaxPane.getText();
    }

    @Override
    public void setResult(String query, String[] headers, Object data, SQLWarning warning) {
        JComponent comp;
        try {
            String[][] arr = (String[][]) data;
            JTable table = new TabelWithToolType(arr, headers);
            JScrollPane tableScroll = new JScrollPane(table);
            tableScroll.setRowHeaderView(getNumbers(arr.length, arr[0].length, table));
            comp = tableScroll;
        } catch (Exception ex) {
            comp = new Panel(String.valueOf(data));
        }

        final JTabbedPane tw = new JTabbedPane(JTabbedPane.BOTTOM);
        tw.addTab(i18n.getResult(), comp);

        StringBuilder sb = new StringBuilder().append(i18n.getQuery())
                .append(":\n").append(query).append("\n").append("\n");

        if (warning != null) {

            while (warning != null) {
                sb.append(warning.toString()).append("\n");
                warning = warning.getNextWarning();
            }
        }

        JTextArea ta = new JTextArea(sb.toString());
        ta.setEditable(false);
        tw.addTab(i18n.getLog(), new JScrollPane(ta));

        SwingUtilities.invokeLater(new Runnable() {
            @Override public void run() {
                tabWindow.addTab(i18n.getQuery(), null, tw, getText());
            }
        });
//        tabWindow.addTab(i18n.getQuery(), null, tw, getText());
    }

    @Override
    public void setError(final Exception ex) {
        final ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ex.printStackTrace(new PrintStream(bout));
        SwingUtilities.invokeLater(new Runnable() {
            @Override public void run() {
                tabWindow.addTab("error", new JScrollPane(
                        new JEditorPane("", bout.toString())));
            }
        });
    }

    private JComponent getNumbers(int row, int col, JTable table) {
        if (row < 1){
            return null;
        }

        DefaultTableModel rowheadmodel = new DefaultTableModel(row, col);
        JTable rowHeaderTable = new JTable(rowheadmodel);
        rowheadmodel.setColumnCount(1);
        rowheadmodel.setColumnIdentifiers(new Object[]{""});
        rowHeaderTable.setEnabled(false);
        rowHeaderTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        rowHeaderTable.getColumnModel().getColumn(0).setPreferredWidth(row);

        // Default settings for mapping rowHeaderTable  browser
        RowHeaderRenderer rh = new RowHeaderRenderer(table);
        rowHeaderTable.setDefaultRenderer(rowHeaderTable.getColumnClass(0), rh);

        int width = rowHeaderTable.getColumnModel().getColumn(0).getPreferredWidth();
        rowHeaderTable.setPreferredScrollableViewportSize(new Dimension(width, 0));

        return rowHeaderTable;
    }

    class Panel extends JComponent {

        public static final int RECT_WIDTH = 250;
        public static final int RECT_HEIGHT = 50;
        private String string;

        public Panel(String string) {
            this.string = string;
            setToolTipText(string);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            
            Dimension s = getSize();
            int x = (s.width - RECT_WIDTH) / 2;
            int y = (s.height - RECT_HEIGHT) / 2;
            g2.setColor(Color.WHITE);
            g2.fill(new Double(5, 5, s.width - 10, s.height - 10, 10, 10));
            
            g2.setStroke(new BasicStroke(3.0f, 0, 0, 2.0f, new float[]{10.0f}, 0.0f));
            g2.setColor(Color.LIGHT_GRAY);
            g2.fill(new Double(x, y, RECT_WIDTH, RECT_HEIGHT, 10, 10));
            
            int width = g2.getFontMetrics().stringWidth(string);
            int height = g2.getFontMetrics().getAscent();
            int sx = x + (RECT_WIDTH - width) / 2;
            int sy = y + (RECT_HEIGHT /*- height / 2*/) / 2;

            g2.setColor(Color.WHITE);
            g2.drawString(string, sx, sy);
        }
    }
}
